package com.atguigu.lease.common.utils;

import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.util.StringUtils;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * @BelongsProject: lease
 * @BelongsPackage: com.atguigu.lease.common.utils
 * @Author: jiangyi
 * @CreateTime: 2025-08-21  15:25
 * @Description: TODO
 * @Version: 1.0
 */
public class JwtUtil {
    // Token过期时间：1小时（60分钟 * 60秒 * 1000毫秒）
    // 使用long类型避免整数溢出，L后缀明确表示long类型 3600,000
    private static long tokenExpiration = 60 * 60 * 1000L;

    // Token签名密钥：使用HMAC-SHA算法
    // 密钥应该从配置文件中读取，硬编码在代码中存在安全风险(随意设置)
    private static SecretKey tokenSignKey = Keys.hmacShaKeyFor("hjhsdhbjsbRsnbdxiijjsnnwdddsWqsff".getBytes());

    /**
     * 创建JWT Token
     * @param userId 用户ID - 作为claim存储在Token中
     * @param username 用户名 - 作为claim存储在Token中
     * @return 编码后的JWT Token字符串
     */
    // 自定义设置JWT令牌
    public static String createToken(Long userId, String username) {
        String token = Jwts.builder()
                // 以下为设置payload（有效载荷）
                .setSubject("USER_INFO")  // 设置主题，标识Token用途（随意设置）
                 // 官方set设置过期时间（设置的是过期的时间点比如 17.50 + 1h = 18.50）
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
                .claim("userId", userId)  // 自定义claim：用户ID
                .claim("username", username)  // 自定义claim：用户名
                // 以下为设置signature（签名）
                .signWith(tokenSignKey, SignatureAlgorithm.HS256) // 使用密钥签名
                .compressWith(CompressionCodecs.GZIP)  // 使用GZIP压缩，减少Token长度
                // 创建并返回Token字符串
                .compact();  // 生成最终的Token字符串
        return token;
    }

    /**
     * 解析JWT Token
     * @param token JWT Token字符串 已知信息：[密钥、ip...]
     * @return Claims对象，包含Token中的所有声明信息 --- 需要解析的声明信息
     * @throws LeaseException 当Token过期或无效时抛出业务异常
     */

    public static Claims parseToken(String token) {
        if (!StringUtils.hasText(token)) {
            throw new LeaseException(ResultCodeEnum.TOKEN_INVALID);
        }
        try {
            Jws<Claims> claimsJws = Jwts.parserBuilder()
                    .setSigningKey(tokenSignKey)  // 设置验证签名所需的密钥
                    .build().parseClaimsJws(token);  // 解析并验证Token
            return claimsJws.getBody();  // 解析结果：返回Token的有效载荷（Payload）== claims
        } catch (ExpiredJwtException e) {
            // Token已过期异常
            throw new LeaseException(ResultCodeEnum.TOKEN_EXPIRED);
        } catch (JwtException e) {
            // 其他JWT相关异常（签名无效、格式错误等）
            throw new LeaseException(ResultCodeEnum.TOKEN_INVALID);
        }
    }
}
